home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / dev / c / ExtrasLib.lha / ExtrasLib / Source / Thread.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-17  |  9.2 KB  |  437 lines

  1. #ifndef EXTRAS_THREADS_H
  2. #include <extras/threads.h>
  3. #endif
  4.  
  5. #include <clib/extras/thread_protos.h>
  6.  
  7. #include <dos.h>
  8. #include <strings.h>
  9. //#define DEBUG
  10. #include <debug.h>
  11.  
  12. #include <clib/alib_protos.h>
  13.  
  14. #include <dos/dos.h>
  15. #include <dos/dostags.h>
  16. #include <exec/memory.h>
  17.  
  18. #include <proto/dos.h>
  19. #include <proto/exec.h>
  20. #include <proto/utility.h>
  21.  
  22. ULONG my_AToI(STRPTR Str);
  23.  
  24. /* internal use */
  25. struct InitThread
  26. {
  27.   struct Task *it_CreaterTask;
  28.   BYTE it_Signal;
  29.   BYTE it_RetVal;
  30.   struct Library *it_ModuleBase;
  31.   struct Thread *it_Thread;
  32.   void __asm (*it_MsgHandler)(register __a0 struct Thread *T,
  33.                               register __a1 struct ThreadMessage *Msg);
  34. };
  35.  
  36. void SingleMsgPort(struct MsgPort *MP);
  37. void __asm __saveds ThreadEntry(register __a0 STRPTR Args);
  38. void __asm __saveds ThreadSubEntry(register __a0 struct InitThread *it,
  39.                                    register __a6 APTR LibBase);
  40.  
  41. struct ThreadMessage *InThreadGetMsg(struct Thread *T);          // Used by message to get messages for thread
  42.  
  43. /****** extras.lib/thread_StartThread ******************************************
  44. *
  45. *   NAME
  46. *       thread_StartThread -- Create a thread.
  47. *
  48. *   SYNOPSIS
  49. *       Thread thread_StartThread(Tags)
  50. *
  51. *       struct Thread *thread_StartThread(Tag, ... );
  52. *
  53. *   FUNCTION
  54. *       Creates and starts a new thread (Process).
  55. *
  56. *   INPUTS
  57. *       Tags - TagList (on stack)
  58. *         TA_Name - Name of thread, defaults to "Thread".
  59. *         TA_Stack - Stacksize, default 8192.
  60. *         TA_Priority - default -1
  61. *         TA_MsgHandler - Function to handle thread messages.
  62. *         TA_UserData - (APTR)
  63. *
  64. *   RESULT
  65. *       Pointer to the newly created Thread, or NULL on failure.
  66. *       The Thread stucture is ReadOnly, except for
  67. *         t_Node, UserData and ThreadData
  68. *
  69. *   NOTES
  70. *       It's suggested that ThreadData be used store local data
  71. *       for the Thread.
  72. *
  73. *   BUGS
  74. *
  75. *   SEE ALSO
  76. *
  77. ******************************************************************************
  78. *
  79. */
  80.  
  81. struct Thread *thread_StartThread(ULONG Tags, ... )
  82. {
  83.   struct TagItem *tl;
  84.   struct Thread *thread;
  85.   struct Process *proc=0;
  86.   struct InitThread *init;
  87.   UBYTE initaddr[11];
  88.   BPTR input,output=0;
  89.   BYTE sigbit;   
  90.   APTR func;
  91.  
  92.   thread=0;
  93.   tl=(APTR)&Tags;
  94.  
  95.   if(func=(APTR)GetTagData(TA_MsgHandler, 0, tl))
  96.   {
  97.     if(thread=AllocVec(sizeof(*thread),MEMF_CLEAR|MEMF_PUBLIC))
  98.     {
  99.       thread->UserData=(APTR)GetTagData(TA_UserData, 0, tl);
  100.       
  101.       if((sigbit=AllocSignal(-1))!=-1)
  102.       {
  103.         if(init=AllocVec(sizeof(struct InitThread),MEMF_PUBLIC|MEMF_CLEAR))
  104.         {
  105.           init->it_CreaterTask  =FindTask(0);
  106.           init->it_Signal      =sigbit;
  107.           init->it_ModuleBase  =(struct Library *)getreg(REG_A6);  
  108.           init->it_Thread      =thread;
  109.           init->it_MsgHandler  =func;
  110.     
  111.           stci_d(initaddr,(LONG)init);
  112.               
  113.           if(input=Open((STRPTR)"NIL:",MODE_OLDFILE))
  114.           {
  115.             if(output=Open((STRPTR)"NIL:",MODE_NEWFILE))
  116.             {
  117. //              DKP("Creating Proc\n");
  118.     
  119.               if(proc=CreateNewProcTags(NP_Input         ,input,
  120.                                         NP_Output        ,output,
  121.                                         NP_Entry         ,ThreadEntry,
  122.                                         NP_Name          ,GetTagData(TA_Name,           (ULONG)"Thread", tl),
  123.                                         NP_StackSize     ,GetTagData(TA_Stack,          8192,           tl),
  124.                                         NP_Arguments     ,initaddr,
  125.                                         NP_Priority      ,GetTagData(TA_Priority,       -1,             tl),
  126.                                         TAG_DONE))
  127.               {
  128.          //       DKP("Proc Created - Waiting for Signal  it=%8lx a6=%8lx\n",init,init->it_ModuleBase);
  129.                 Wait(1<<sigbit);
  130.            //     DKP("Signaled  RetVal=%ld\n",init->it_RetVal);
  131.                 if(!init->it_RetVal)
  132.                   proc=0;
  133.               }
  134.             }
  135.           }
  136.           if(!proc)
  137.           {
  138.             if(input)
  139.               Close(input);
  140.             if(output)
  141.               Close(output);
  142.           }
  143.           FreeVec(init);
  144.         }
  145.         FreeSignal(sigbit);
  146.       }
  147.       if(!thread->t_Process)
  148.       {
  149.         FreeVec(thread);
  150.         thread=0;
  151.       }
  152.     }
  153.   }
  154. //  DKP("Leaving CreateInput\n");
  155.   return(thread);
  156. }      
  157.  
  158. /****** extras.lib/thread_EndThread ******************************************
  159. *
  160. *   NAME
  161. *       thread_EndThread -- end a thread.
  162. *
  163. *   SYNOPSIS
  164. *
  165. *
  166. *
  167. *
  168. *
  169. *
  170. *   FUNCTION
  171. *
  172. *
  173. *   INPUTS
  174. *
  175. *   RESULT
  176. *
  177. *   EXAMPLE
  178. *
  179. *   NOTES
  180. *       Note, this function waits for a reply.
  181. *
  182. *   BUGS
  183. *
  184. *   SEE ALSO
  185. *
  186. ******************************************************************************
  187. *
  188. */
  189.  
  190.  
  191. void thread_EndThread(struct Thread *Thread, APTR NullForNow)
  192. {
  193.   struct ThreadMessage diemsg;
  194.   struct MsgPort mp;
  195.  
  196.   if(Thread)
  197.   {
  198.     SingleMsgPort(&mp);
  199.   
  200.     diemsg.tm_Msg.mn_ReplyPort     =∓
  201.     diemsg.tm_Msg.mn_Length        =sizeof(diemsg);
  202.     diemsg.tm_Command              =TMSG_DIE;
  203.     
  204.     if(Thread->t_MsgPort)
  205.     {
  206.       PutMsg(Thread->t_MsgPort,(struct Message *)&diemsg);
  207. //      WaitForReply(&diemsg);
  208.       WaitPort(&mp);
  209.     }
  210.     FreeVec(Thread);
  211.   }
  212. }
  213.  
  214. void SingleMsgPort(struct MsgPort *MP)
  215. {
  216.   MP->mp_Flags=PA_SIGNAL;
  217.   MP->mp_SigBit=SIGF_SINGLE; 
  218.   MP->mp_SigTask=FindTask(0);
  219.   NewList(&MP->mp_MsgList);
  220. }
  221.  
  222. /* Meat & Potatoes */
  223.  
  224. void __asm __saveds ThreadEntry(register __a0 STRPTR Args)
  225. {
  226.   struct InitThread *it;
  227.   
  228.   it=(struct InitThread *)my_AToI(Args);
  229.  
  230.   ThreadSubEntry(it,it->it_ModuleBase);
  231. }
  232.  
  233. void __asm __saveds ThreadSubEntry(register __a0 struct InitThread *it,
  234.                                    register __a6 APTR LibBase)
  235. {
  236.   struct MsgPort *mp;
  237.   struct Thread *me;
  238.   struct ThreadMessage *msg,*diemsg=0;
  239.   ULONG   isig,allsigs,sig; 
  240.   BOOL    go=TRUE;
  241.   void __asm (*MsgHandler)(register __a0 struct Thread *T,
  242.                            register __a1 struct ThreadMessage *Msg,
  243.                            register __a6 APTR LibBase);
  244.  
  245.   if(mp=CreateMsgPort())
  246.   {
  247.     isig=1<<mp->mp_SigBit;
  248.  
  249.     me=it->it_Thread;    
  250.     it->it_Thread->t_MsgPort = mp;
  251.     it->it_Thread->t_Process = (struct Process *)FindTask(0);
  252.     MsgHandler=it->it_MsgHandler;
  253.  
  254.     it->it_RetVal=1;  /* Signal creator */
  255.     Signal(it->it_CreaterTask,1<<it->it_Signal);
  256.  
  257.     it=0;  /* don't want to signal again, see below */
  258.  
  259.     allsigs=isig;
  260.     while(go)
  261.     {
  262. //      DKP("Waiting for %8lx\n",allsigs);
  263.       
  264. //      sig=Wait(allsigs);
  265.       sig=Wait(-1);
  266. //      DKP("Signal recieved %8lx\n",sig);
  267.       
  268.       if(sig & isig)
  269.       {
  270. //        DKP("Message signal recieved\n");
  271.         while(msg=(struct ThreadMessage *)GetMsg(mp))
  272.         {
  273. //          DKP("Msg @ 0x%08lx\n",msg);
  274.           switch(msg->tm_Command)
  275.           {
  276.             case TMSG_DIE:
  277.               MsgHandler(me,msg,LibBase);
  278.               diemsg=msg;
  279.               go=0;
  280.               break;
  281.             default:
  282.               MsgHandler(me,msg,LibBase);
  283.               break;
  284.           }
  285.           ReplyMsg((APTR)msg);
  286.         }
  287.       }
  288.       
  289.       if(sig & ~(isig))
  290.       {
  291.         struct TMsg_Signal tms;
  292.         
  293.         tms.TMsg.tm_Msg.mn_Length=sizeof(tms);
  294.         tms.TMsg.tm_Command=TMSG_SIGNAL;
  295.         tms.Signal=sig;
  296.         
  297.         MsgHandler(me,(APTR)&tms,LibBase);
  298.       }
  299.       
  300.     }
  301.     DeleteMsgPort(mp);  
  302.   }
  303.   
  304.   if(it)
  305.   {
  306.     it->it_RetVal=0;  /* Signal creator */
  307.     Signal(it->it_CreaterTask,1<<it->it_Signal);
  308.   }
  309.   
  310.   if(diemsg)
  311.     ReplyMsg((struct Message *)diemsg);
  312. }
  313.  
  314. ULONG my_AToI(STRPTR Str)
  315. {
  316.   ULONG i=0;
  317.   
  318.   while(*Str>'9' || *Str<'0' && *Str)
  319.     Str++;
  320.   
  321.   while(*Str<='9' && *Str>='0')
  322.   {
  323.     i=(i*10)+((*Str)-'0');
  324.     Str++;
  325.   }
  326.   return(i);
  327. }
  328.  
  329. /****** extras.lib/thread_PutTMsg ******************************************
  330. *
  331. *   NAME
  332. *       thread_PutTMsg -- Send a ThreadMessage to a thread.
  333. *
  334. *   SYNOPSIS
  335. *
  336. *
  337. *
  338. *
  339. *
  340. *
  341. *   FUNCTION
  342. *
  343. *
  344. *   INPUTS
  345. *
  346. *   RESULT
  347. *
  348. *   EXAMPLE
  349. *
  350. *   NOTES
  351. *       Note, this function does not wait for a reply.
  352. *
  353. *   BUGS
  354. *
  355. *   SEE ALSO
  356. *
  357. ******************************************************************************
  358. *
  359. */
  360.  
  361.  
  362. BOOL thread_PutTMsg(struct Thread *Thread, struct ThreadMessage *TM)
  363. {
  364.   if(Thread)
  365.   {
  366.     if(Thread->t_MsgPort)
  367.     {
  368.       PutMsg(Thread->t_MsgPort,(struct Message *)TM);
  369.       return(1);
  370.     }
  371.   }
  372.   return(0);
  373. }
  374.  
  375.  
  376. /****** extras.lib/thread_PutTMsg_TagList ******************************************
  377. *
  378. *   NAME
  379. *       thread_PutTMsg_TagList -- Send a TagListTMsg to a thread.
  380. *
  381. *   SYNOPSIS
  382. *
  383. *
  384. *
  385. *
  386. *
  387. *
  388. *   FUNCTION
  389. *
  390. *
  391. *   INPUTS
  392. *
  393. *   RESULT
  394. *
  395. *   EXAMPLE
  396. *
  397. *   NOTES
  398. *       Note, this function waits for a reply.
  399. *
  400. *   BUGS
  401. *
  402. *   SEE ALSO
  403. *
  404. ******************************************************************************
  405. *
  406. */
  407.  
  408.  
  409. ULONG thread_PutTMsg_TagList(struct Thread *Thread, ULONG Command, ULONG Tag, ...)
  410. {
  411.   struct TMsg_TagList msg;
  412.   struct MsgPort mp;
  413.  
  414.   if(Thread)
  415.   {
  416.     SingleMsgPort(&mp);
  417.   
  418.     msg.tm_Msg.mn_ReplyPort     =∓
  419.     msg.tm_Msg.mn_Length        =sizeof(msg);
  420.     msg.tm_Command              =Command;
  421.     msg.tm_TagList              =(APTR)&Tag;
  422.     
  423.     if(Thread->t_MsgPort)
  424.     {
  425.       PutMsg(Thread->t_MsgPort,(struct Message *)&msg);
  426. //      WaitForReply(&diemsg);
  427.  
  428.       while(&msg!=(APTR)GetMsg(&mp))
  429.       {
  430.         WaitPort(&mp);
  431.       }
  432.       return(msg.tm_RetVal);
  433.     }
  434.   }
  435.   return(0);
  436. }
  437.